﻿using System.Collections.Generic;
using System.Threading;

namespace HCore
{
    public partial class Server
    {
        private class ServerBattleState : State<Server>
        {
            private List<int> _checkSums;

            public ServerBattleState(Server owner) : base(owner)
            {
            }

            public override void Enter()
            {
                _checkSums = new List<int>();

                _owner._networkMgr.Register(PacketType.TurnData, TurnDataHandle);

                Server server = _owner;
                server.Log("Enter Battle 3");
                Thread.Sleep(1000);
                server.Log("Enter Battle 2");
                Thread.Sleep(1000);
                server.Log("Enter Battle 1");
                Thread.Sleep(1000);
                server.Log("Battle Start");

                var networkMgr = server._networkMgr;
                var clientProxies = server._clientProxies;
                // 向所有玩家发起开始战斗
                foreach (var kv in clientProxies)
                {
                    OutputMemeryBitStream output = new OutputMemeryBitStream();
                    output.WriteByte(PacketType.Start);
                    networkMgr.Send(output.GetBuffer(), output.GetByteLength(), kv.Key);
                }

                var timer = server._timer;
                timer.Start();
            }

            private void TurnDataHandle(SessionPacket sessionPacket)
            {
                var clientProxies = _owner._clientProxies;
                uint sessionId = sessionPacket.sessionId;
                if (!clientProxies.TryGetValue(sessionId, out var fromProxy))
                {
                    // 不处理新玩家了
                    return;
                }

                InputMemoryBitStream intput = sessionPacket.input;
                TurnData turnData = new TurnData();
                turnData.Read(intput);
                CheckSync(turnData);
                fromProxy.RecTurnData(turnData);
            }

            public override void Execute()
            {
                Server server = _owner;
                var clientProxies = _owner._clientProxies;
                var networkMgr = _owner._networkMgr;
                var timer = server._timer;
                if (timer.ReadyForNextFrame())
                {
                    if (timer.frameCount  > 0 && timer.frameCount % GameDefine.FRAMES_PER_TURN == 0)
                    {
                        OutputMemeryBitStream output = new OutputMemeryBitStream();
                        output.WriteByte(PacketType.TurnData);
                        output.WriteInt(timer.frameCount / GameDefine.FRAMES_PER_TURN);
                        output.WriteInt(clientProxies.Count);
                        // 输入数据同步给所有玩家
                        foreach (var kv in clientProxies)
                        {
                            ClientProxy proxy = kv.Value;
                            TurnData turnData = proxy.SendTurnData((int) timer.frameRate, proxy.playerId);
                            turnData.Write(output);
                        }

                        foreach (var kv in clientProxies)
                        {
                            // 给其他玩家同步消息
                            networkMgr.Send(output, kv.Key);
                        }
                    }

                    // 下一帧
                    timer.IntoNextFrame();
                }
            }

            private bool CheckSync(TurnData turnData)
            {
                int playerId = turnData.playerId;
                int turnCount = turnData.turnCount;
                int checkSum = turnData.checkSum;
                int random = turnData.randomValue;
                Debug.Assert(turnCount <= _checkSums.Count);

                if (turnCount == _checkSums.Count)
                {
                    _checkSums.Add(checkSum);
                }
                else if (turnCount < _checkSums.Count)
                {
                    if (_checkSums[turnCount] != checkSum)
                    {
                        Logger.LogError("checkSum error turnCount: " + turnCount);
                        return false;
                    }
                }

                return true;
            }

            public override void Exit()
            {
                _owner._networkMgr.Unregister(PacketType.TurnData);
                Server server = _owner;
                server.Log("Exit Battle");
            }
        }
    }
}